package com.yzion.baselib.utils

import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Outline
import android.util.LayoutDirection
import android.view.Gravity
import android.view.View
import android.view.ViewOutlineProvider
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.TextView
import android.widget.Toast
import androidx.core.animation.doOnEnd
import androidx.core.text.TextUtilsCompat
import com.blankj.utilcode.util.ClickUtils
import com.blankj.utilcode.util.ConvertUtils
import com.blankj.utilcode.util.EncodeUtils
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.LanguageUtils
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.TimeUtils
import com.blankj.utilcode.util.Utils
import com.hjq.toast.ToastParams
import com.hjq.toast.Toaster
import com.hjq.toast.config.IToastStyle
import com.yzion.baselib.app.IAppProvider
import com.yzion.baselib.http.ApiHelper
import com.yzion.baselib.http.BaseResponse
import okhttp3.Request
import okio.Buffer
import retrofit2.Response
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.Locale
import kotlin.math.abs

var lastClickTime = 0L
fun isFastDoubleClick(interval: Long = 500): Boolean {
    val currentTime = System.currentTimeMillis()
    val isFast = currentTime - lastClickTime < interval
    lastClickTime = currentTime
    return isFast
}

/**
 * Enables marquee effect on a TextView
 *
 * @param textView The TextView to enable marquee effect on
 */
fun TextView.enableMarquee() {
    isFocusable = true
    isFocusableInTouchMode = true
    requestFocus()
    setSingleLine()
    ellipsize = android.text.TextUtils.TruncateAt.MARQUEE
    marqueeRepeatLimit = -1 // Set to -1 for infinite marquee
    isSelected = true // This is necessary to start marquee
}

/**
 * Disables marquee effect on a TextView
 *
 * @param textView The TextView to disable marquee effect on
 */
fun TextView.disableMarquee() {
    isFocusable = false
    isFocusableInTouchMode = false
//    setSingleLine(false)
    ellipsize = null
    marqueeRepeatLimit = 0
    isSelected = false
}

/**
 * 正确处理截断字符串的长度
 */
fun String?.truncateString(maxLength: Int): String {
    if (this.isNullOrEmpty() || maxLength <= 0) return ""

    val ellipsis = "..."
    if (this.length <= maxLength) return this

    var endIndex = 0
    var currentLength = 0

    while (endIndex < this.length && currentLength < maxLength) {
        val currentChar = this[endIndex]
        if (Character.isHighSurrogate(currentChar) && endIndex + 1 < this.length && Character.isLowSurrogate(
                this[endIndex + 1]
            )
        ) {
            // If the current character is a high surrogate and the next character is a low surrogate, consider them together.
            if (currentLength + 2 > maxLength) break
            currentLength += 2
            endIndex += 2
        } else {
            currentLength++
            endIndex++
        }
    }

    return if (endIndex < this.length) {
        this.substring(0, endIndex) + ellipsis
    } else {
        this
    }
}

fun <T> ArrayList<T>.toSubList(count: Int): ArrayList<T> {
    return if (size > count) {
        subList(0, count).toCollection(arrayListOf())
    } else {
        this
    }
}

/**
 * 保留指定的小数位数
 */
fun Float.toShortFloat(decimalPlaces: Int): Float {
    return BigDecimal(this.toDouble()).setScale(decimalPlaces, RoundingMode.HALF_UP).toFloat()
}

/**
 * 格式化数字表示
 */
fun Float.toCommaString(): String {
    try {
        return DecimalFormat("#,##0.00##").format(this)
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return ""
}

/**
 * 格式化数字表示
 */
fun Double.toCommaString(): String {
    try {
        return DecimalFormat(
            "#,##0.00######",
            DecimalFormatSymbols.getInstance(Locale.ENGLISH)
        ).format(this)
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return ""
}

/**
 * 把数字格式化成每三位，用逗号隔开的字符串
 */
fun Int.toCommaString(): String {
    try {
        return DecimalFormat("#,###", DecimalFormatSymbols.getInstance(Locale.ENGLISH)).format(this)
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return ""
}

/**
 * 格式化数字表示
 */
fun Long.toCommaString(): String {
    try {
        return DecimalFormat("#,###", DecimalFormatSymbols.getInstance(Locale.ENGLISH)).format(this)
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return ""
}

fun Long.toDateString(p: String? = null): String {
    try {
        return if (p == null) {
            TimeUtils.millis2String(this)
        } else {
            TimeUtils.millis2String(this, p)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return ""
}

/**
 * 将文件大小转换为带有适当单位（K, M, G）的字符串
 */
fun Long?.toMiniSize(): String {
    if (this == null) return ""
    val units = arrayOf("B", "K", "M", "G")
    var size = this.toDouble()
    var unitIndex = 0

    while (size >= 1024 && unitIndex < units.size - 1) {
        size /= 1024
        unitIndex++
    }

    return String.format(Locale.ENGLISH, "%.1f%s", size, units[unitIndex])
}


/**
 * ms->播放进度时间：00:00:00
 */
fun Long?.toDurationTimeString(): String {
    if (this == null) return ""
    var timeMs = this
    val prefix = if (timeMs < 0L) "" else ""
    timeMs = abs(timeMs)
    val totalSeconds = timeMs / 1000L
    val seconds = totalSeconds % 60L
    val minutes = totalSeconds / 60L % 60L
    val hours = totalSeconds / 3600L
    return if (hours > 0L) String.format(
        Locale.ENGLISH,
        "%s%d:%02d:%02d",
        prefix,
        hours,
        minutes,
        seconds
    ) else String.format(
        Locale.ENGLISH, "%s%02d:%02d", prefix, minutes, seconds
    )
}


//移除文件扩展名
fun String?.removeExtension(): String {
    if (isNullOrEmpty()) return ""
    val lastIndex = lastIndexOf('.')
    return if (lastIndex == -1) {
        // 没有找到扩展名，返回原始文件名
        this
    } else {
        // 找到了扩展名，返回去除扩展名的部分
        substring(0, lastIndex)
    }
}

fun clearLog() {
    LogUtils.getLogFiles().forEach {
        runCatching {
            it.delete()
        }
    }
}

fun Any?.toJson(): String {
    if (this != null) {
        return runCatching {
            GsonUtils.toJson(this)
        }.getOrDefault("")
    }
    return ""
}

fun isRTLLayout(): Boolean {
    //先获取应用内语言，返回空说明没改动过，默认跟随系统
    var local = LanguageUtils.getAppliedLanguage()
    if (local == null) {
        //获取系统语言
        local = LanguageUtils.getSystemLanguage()
    }
    return TextUtilsCompat.getLayoutDirectionFromLocale(local) == LayoutDirection.RTL
}

fun String.base64Decode(): String {
    return String(EncodeUtils.base64Decode(this))
}

fun String.base64Encode(): String {
    return String(EncodeUtils.base64Encode(this))
}

fun Int.dp(): Int {
    return ConvertUtils.dp2px(this.toFloat())
}

fun Double.dp(): Int {
    return ConvertUtils.dp2px(this.toFloat())
}

/**
 * 通用N次点击回调
 */
inline fun View.onMultiClick(clickCount: Int, crossinline onClick: (v: View) -> Unit) {
    setOnClickListener(object : ClickUtils.OnMultiClickListener(clickCount) {

        override fun onTriggerClick(v: View) {
            onClick.invoke(v)
        }

        override fun onBeforeTriggerClick(v: View, count: Int) {
        }
    })
}

/**
 * 点击动画
 */
fun clickAnim(view: View, onEnd: ((View) -> Unit)? = null) {
    // 设置缩放动画
    val scaleX = ObjectAnimator.ofFloat(view, View.SCALE_X, 0.9f, 1.05f, 1f)
    val scaleY = ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.9f, 1.05f, 1f)
    scaleX.duration = 200
    scaleY.duration = 200
    scaleX.interpolator = AccelerateDecelerateInterpolator()
    scaleY.interpolator = AccelerateDecelerateInterpolator()

    // 同时播放X和Y方向的缩放动画
    val animatorSet = AnimatorSet()
    animatorSet.play(scaleX).with(scaleY)
    animatorSet.doOnEnd {
        onEnd?.invoke(view)
    }
    animatorSet.start()
}

/**
 * 通用防抖单击回调
 */
inline fun View.onSingleClick(anim: Boolean = false, crossinline onClick: (v: View) -> Unit) {
    setOnClickListener(object : ClickUtils.OnDebouncingClickListener(false, 500) {
        override fun onDebouncingClick(v: View) {
            if (anim) clickAnim(v) {
                onClick.invoke(v)
            } else onClick.invoke(v)
        }
    })
}

/**
 * 全局统一Toast调用
 * 默认样式的Toast，可以通过复写BaseApp中的createToastView来自定义样式，具体参见源码
 */
fun showToast(msg: String?) {
    ThreadUtils.runOnUiThread {
        runCatching {
            if (msg.isNullOrEmpty()) return@runCatching
            val v = (Utils.getApp() as IAppProvider).createToastView(Utils.getApp())
            Toaster.show(ToastParams().apply {
                style = object : IToastStyle<View> {
                    override fun createView(context: Context): View {
                        return v.getView()
                    }

                    override fun getGravity(): Int {
                        return Gravity.BOTTOM
                    }

                    override fun getYOffset(): Int {
                        return ConvertUtils.dp2px(120f)
                    }

                }
                duration = Toast.LENGTH_LONG
                text = msg
                crossPageShow = false
            })

//        v.setText(msg)
//        ToastUtils.getDefaultMaker()
//            .setGravity(Gravity.BOTTOM, 0, ConvertUtils.dp2px(120f))
//            .show(v.getRootView())
        }
    }
}

/**
 * 设置view圆角
 *
 * @param radius
 * @return
 */
fun View.setCornerRound(radius: Int) {
    outlineProvider = object : ViewOutlineProvider() {
        override fun getOutline(view: View, outline: Outline) {
            outline.setRoundRect(0, 0, view.width, view.height, radius.toFloat())
        }
    }
    clipToOutline = true
}

/**
 * body内容输出成String
 */
fun Request.bodyToString(): String? {
    return try {
        val copy = newBuilder().build()
        val buffer = Buffer()
        copy.body!!.writeTo(buffer)
        buffer.readUtf8()
    } catch (e: Exception) {
        null
    }
}

/**
 * view转bitmap，用于截图,
 *
 *
 * @param v View
 * @return Bitmap
 */
fun View.viewToBitmap(): Bitmap {
    val w: Int = width
    val h: Int = height
    val bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
    val c = Canvas(bmp)
    draw(c)
    return bmp
}

/**
 * 判断请求是否成功，一般用于同步方法中的判断响应是否成功
 * 1.http状态成功，if the code is in [200..300), which means the request was successfully received,
 * understood, and accepted.
 * 2.服务器请求返回成功，该成功的代码是服务器自定义的，需要在HttpConfig中的configResponseSuccessCode方法中定义
 */
fun <T : BaseResponse<*>> Response<T>.isSuccess(): Boolean {
    //根据当前请求地址找到baseUrl
    val baseUrl =
        ApiHelper.get().baseUrlList.find { raw().request.url.toString().startsWith(it) }
            ?: ""
    //根据baseUrl获取HttpConfig
    val config = ApiHelper.get().getHttpConfig(baseUrl)
    if (config != null) {
        if (isSuccessful && body()?.code() == config.configResponseSuccessCode()) {
            return true
        }
    }
    return false
}

fun cancelAllRequest() {
    //取消其他正在请求的接口
    ApiHelper.get().httpClientMap.forEach {
        it.value.dispatcher.cancelAll()
    }

}